package com.cy.model;

import com.cy.BasicModel;
import com.cy.ext.plugin.tablebind.TableBind;
import com.cy.utils.SimpleSqlUtils;
import com.google.common.collect.Lists;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Record;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@SuppressWarnings("serial")
@TableBind(tableName="encryption_log",pkName = "log_id")
public class EncryptionLog extends BasicModel<EncryptionLog> {

    public static final EncryptionLog dao = new EncryptionLog();
    public static final String SELECT_ALL = "`log_id`,`user_id`,`device_id`,`tn`,`raw`,`msg`,`os`,`remark`,`status`,`create_time`,`result`";

    /**
     * 统计返回结果
     */
    public Map<String, Object> sumResultByPage(Integer pageNumber, Integer pageSize, String startTime, String endTime) {
        ArrayList<String> selects = Lists.newArrayList("IFNULL(result,'null') AS yField", "COUNT(1) AS xField");
        ArrayList<String> tables = Lists.newArrayList("encryption_log_archived");
        ArrayList<String> wheres = new ArrayList<>(2);
        if (StringUtils.isNotBlank(startTime))
            wheres.add("create_time >= '"+ startTime +"'");
        if (StringUtils.isNotBlank(endTime))
            wheres.add("create_time <= '"+ endTime +"'");
        ArrayList<String> groupBy = Lists.newArrayList("yField");

        //查询总记录
        ArrayList<String> countSelect = Lists.newArrayList("COUNT(1)");
        ArrayList<String> countTable = Lists.newArrayList("("+ SimpleSqlUtils.generateSql(selects, tables, null, wheres, groupBy, null) +") temp");
        String countSql = SimpleSqlUtils.generateSql(countSelect, countTable, null, null, null, null);
        Long count = Db.queryLong(countSql);

        //分页查询
        int limitStart = (pageNumber - 1) * pageSize;
        ArrayList<String> orderBy = Lists.newArrayList("xField DESC limit "+ limitStart +","+ pageSize);
        String sql = SimpleSqlUtils.generateSql(selects, tables, null, wheres, groupBy, orderBy);
        List<Record> records = Db.find(sql);

        Map<String, Object> result = new HashMap<>(2);
        ArrayList<String> xField = new ArrayList<>(records.size());
        ArrayList<String> yField = new ArrayList<>(records.size());
        for (Record record : records){
            xField.add(record.<String>get("xField"));
            yField.add(record.<String>get("yField"));
        }
        result.put("xField", xField);
        result.put("yField", yField);
        result.put("pageNumber", pageNumber);//当前页码
        result.put("pageSize", pageSize);//每页记录数
        result.put("totalPage", count == 0 ? 1 : count % pageSize == 0 ? count / pageSize : count / pageSize + 1);//总页数
        result.put("totalRow", count);//总记录数
        return result;
    }

    public Page<EncryptionLog> paginate(Integer pageNumber, Integer pageSize, String column, EncryptionLog model) {
        List<Object> paras = new ArrayList<>();
        StringBuilder sqlExceptSelectBuffer = new StringBuilder("FROM encryption_log_archived WHERE 1=1");
        StringBuilder selectBuffer = new StringBuilder("SELECT ").append(column);
        if (pageNumber == null || pageNumber == 0) {
            pageNumber = 1;
        } else {
            pageNumber++;
        }
        if (pageSize == null || pageSize == 0) {
            pageSize = 20;
        }

        if (model != null) {
            String[] attrNames = model.getAttrNames();
            for (String attrName : attrNames) {
                Object attrValue = model.get(attrName);
                if (attrValue != null) {
                    if("start".equals(attrName)){
                        sqlExceptSelectBuffer.append(" AND `create_time` >= ?");
                    }else if("end".equals(attrName)){
                        sqlExceptSelectBuffer.append(" AND `create_time` <= ?");
                    }else if("result".equals(attrName) && "null".equals(attrValue)){
                        sqlExceptSelectBuffer.append(" AND `result` IS NULL");
                        continue;
                    }else{
                        sqlExceptSelectBuffer.append(" AND `" + attrName + "`=?");
                    }
                    paras.add(attrValue);
                }
            }
        }
        sqlExceptSelectBuffer.append(" ORDER BY `create_time` DESC ");
        if (paras.size() > 0) {
            return paginate(pageNumber, pageSize, selectBuffer.toString(), sqlExceptSelectBuffer.toString(), paras.toArray());
        }
        return paginate(pageNumber, pageSize, selectBuffer.toString(), sqlExceptSelectBuffer.toString());
    }

    public EncryptionLog findLog(EncryptionLog log){
        List<Object> paras = new ArrayList<>();
        StringBuffer sqlExceptSelectBuffer = new StringBuffer("SELECT * FROM encryption_log ");
        sqlExceptSelectBuffer.append(" where 1=1 ");
        if (log != null) {
            String[] attrNames = log.getAttrNames();
            for (String attrName : attrNames) {
                Object attrValue = log.get(attrName);
                if (attrValue != null) {
                    if("start".equals(attrName)){
                        sqlExceptSelectBuffer.append(" AND `create_time` > DATE_FORMAT(?,'%Y-%m-%d %T')");
                    }else if("end".equals(attrName)){
                        sqlExceptSelectBuffer.append(" AND `create_time` < DATE_FORMAT(?,'%Y-%m-%d %T')");
                    }else{
                        sqlExceptSelectBuffer.append(" AND `" + attrName + "`=?");
                    }
                    paras.add(attrValue);
                }
            }
            sqlExceptSelectBuffer.append(" ORDER BY `create_time` DESC ");
        }
        return findFirst(sqlExceptSelectBuffer.toString(),paras.toArray());
    }

    public List<EncryptionLog> findByDeviceId(Long deviceId) {
        return find("select "+SELECT_ALL+" from encryption_log_archived where device_id = ? order by create_time desc", deviceId);
    }

    /**
     * 查询更详细的日志记录（包括APP版本、IP）
     */
    public List<EncryptionLog> findDetailByDeviceAndUser(Long deviceId, Long userId) {
        StringBuilder sql = new StringBuilder(100);
        sql.append(" SELECT u.*, a.ver_name FROM user_info_history u, app_version a");
        sql.append(" WHERE u.app_version_id = a.id");
        sql.append(" AND u.user_id = ?");
        sql.append(" AND u.create_time <= ?");
        sql.append(" ORDER BY u.create_time DESC LIMIT 1");

        List<EncryptionLog> encryptionLogs = find("select * from encryption_log_archived where device_id = ? and user_id = ? order by log_id desc", deviceId, userId);
        for (EncryptionLog encryptionLog : encryptionLogs){
            Record record = Db.findFirst(sql.toString(), encryptionLog.getUserId(), encryptionLog.getCreateTime());
            if (record != null){
                encryptionLog.put("ip", record.get("ip"));
                encryptionLog.put("mobile_phone_model", record.get("mobile_phone_model"));
                encryptionLog.put("operating_system", record.get("operating_system"));
                encryptionLog.put("operating_system_version", record.get("operating_system_version"));
                encryptionLog.put("ver_name", record.get("ver_name"));
                break;
            }
        }
        return encryptionLogs;
    }
    
    public EncryptionLog setLogId (Long logId){
        this.set("log_id",logId);
        return this;
    }

    public Long getLogId(){
        return this.get("log_id");
    }

    public EncryptionLog setUserId(Long userId){
        this.set("user_id",userId);
        return this;
    }

    public Long getUserId(){
        return this.get("user_id");
    }

    public EncryptionLog setDeviceId(Long deviceId){
        this.set("device_id",deviceId);
        return this;
    }

    public Long getDeviceId(){
        return this.get("device_id");
    }

    public Device getDevice(){
        return Device.dao.findById(getDeviceId());
    }

    public EncryptionLog setOs(Long os){
        this.set("os",os);
        return this;
    }

    public Long getOs(){
        return this.get("os");
    }

    public EncryptionLog setStatus(int status){
        this.set("status",status);
        return this;
    }

    public Integer getStatus(){
        return this.get("status");
    }

    public EncryptionLog setResult (String result){
        this.set("result",result);
        return this;
    }

    public String getResult(){
        return this.getStr("result");
    }

    public EncryptionLog setTn(String tn){
        this.set("tn",tn);
        return this;
    }

    public String getTn(){
        return this.getStr("tn");
    }

    public EncryptionLog setRaw(String raw){
        this.set("raw",raw);
        return this;
    }

    public String getRaw(){
        return this.getStr("raw");
    }

    public EncryptionLog setMsg(String msg){
        this.set("msg",msg);
        return this;
    }

    public String getMsg(){
        return this.getStr("msg");
    }

    public EncryptionLog setRemark(String msg){
        this.set("remark",msg);
        return this;
    }

    public String getRemark(){
        return this.getStr("remark");
    }

    public EncryptionLog setCreateTime(Date createTime){
        this.set("create_time",createTime);
        return this;
    }

    public Date getCreateTime(){
        return this.get("create_time");
    }

}
